using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Input;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace MicroSnake
{    
    class GameScreen : Screen
    {
        private GameStatus gameStatus;

        private Timer gameTimer;
        public delegate void GameTimerDelegate();

        private Snake snake;
        private GameBoard gameBoard;

        private Text txtTopTitle;
        private Text txtDifficultyLevelTitle;
        private Text txtDifficultyLevel;
        private Text txtLifesTitle;
        private Text txtLifes;
        private Text txtRoundTitle;
        private Text txtRound;
        private Text txtRemainedMousesTitle;
        private Text txtRemainedMouees;
        private StackPanel mainStackPanel;
        private StackPanel centerStackPanel;
        private StackPanel infoStackPanel;

        private short round;
        private short lifes;
        private short remainedMouses;
        private int timerCounter;

        /// <summary>
        /// Start the game from the first round.
        /// </summary>
        public void StartGame()
        {
            round = 1;
            lifes = 3;

            Rounds.MakeRound(gameBoard, round, ref remainedMouses, ref timerCounter);
            snake = new Snake(gameBoard, 3, 3, 5);

            SetRound(round);
            SetLifes(lifes);
            SetRemainedMouses(remainedMouses);

            gameStatus = GameStatus.Running;
        }

        public GameScreen()
        {
            InitializeComponent();

            //gameTimer = new ExtendedTimer(new TimerCallback(gameTimer_elapsed), null, Timeout.Infinite, Timeout.Infinite);
            gameStatus = GameStatus.NotStarted;
            gameTimer = new Timer(new TimerCallback(gameTimer_elapsed), null, Timeout.Infinite, Timeout.Infinite);
        }

        /// <summary>
        /// Built the menu graphical user interface
        /// </summary>
        private void InitializeComponent()
        {
            mainStackPanel = new StackPanel(Orientation.Vertical);

            // Insert the top panel
            Panel topPanel = new Panel();
            topPanel.Width = SystemMetrics.ScreenWidth;
            topPanel.Height = 20;

            //Rectangle topRect = new Rectangle();
            //topRect.Stroke = null;
            //topRect.Fill = new SolidColorBrush(MicroSnakeColors.MenuItemSelectedBackgroundColor);

            //topPanel.Children.Add(topRect);

            txtTopTitle = new Text()
            {
                Font = Resources.GetFont(Resources.FontResources.NinaB),
                ForeColor = MicroSnakeColors.MenuItemSelectedBackgroundColor,
                HorizontalAlignment = HorizontalAlignment.Left,
                TextAlignment = TextAlignment.Center,
                TextContent = Resources.GetString(Resources.StringResources.Welcome),
                VerticalAlignment = VerticalAlignment.Center,
            };
            topPanel.Children.Add(txtTopTitle);
            topPanel.SetMargin(30, 5, 0, 0);

            mainStackPanel.Children.Add(topPanel);

            // Insert the game body

            centerStackPanel = new StackPanel(Orientation.Horizontal);
            centerStackPanel.Height = SystemMetrics.ScreenHeight - 15 * 2;

            gameBoard = new GameBoard();
            gameBoard.VerticalAlignment = VerticalAlignment.Center;
            gameBoard.SetMargin(10, 5, 5, 0);
            
            centerStackPanel.Children.Add(gameBoard);

            infoStackPanel = new StackPanel(Orientation.Vertical);
            infoStackPanel.SetMargin(10, 10, 0, 0);

                // Add Difficulty Level Text
                txtDifficultyLevelTitle = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.NinaB),
                    ForeColor = MicroSnakeColors.MenuItemSelectedBackgroundColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = Resources.GetString(Resources.StringResources.GameScreenDifficultyLevelTitle),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtDifficultyLevelTitle.SetMargin(0, 0, 0, 5);
                infoStackPanel.Children.Add(txtDifficultyLevelTitle);

                txtDifficultyLevel = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.small),
                    ForeColor = MicroSnakeColors.MenuItemForeColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = Resources.GetString(Resources.StringResources.DifficultyLevelNormal),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtDifficultyLevel.SetMargin(0, 0, 0, 10);
                infoStackPanel.Children.Add(txtDifficultyLevel);

                // Add Round Text
                txtRoundTitle = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.NinaB),
                    ForeColor = MicroSnakeColors.MenuItemSelectedBackgroundColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = Resources.GetString(Resources.StringResources.GameScreenRoundTitle),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtRoundTitle.SetMargin(0, 0, 0, 5);
                infoStackPanel.Children.Add(txtRoundTitle);

                txtRound = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.small),
                    ForeColor = MicroSnakeColors.MenuItemForeColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = round.ToString(),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtRound.SetMargin(0, 0, 0, 10);
                infoStackPanel.Children.Add(txtRound);

                // Add Lifes Text
                txtLifesTitle = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.NinaB),
                    ForeColor = MicroSnakeColors.MenuItemSelectedBackgroundColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = Resources.GetString(Resources.StringResources.GameScreenLifesTitle),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtLifesTitle.SetMargin(0, 0, 0, 5);
                infoStackPanel.Children.Add(txtLifesTitle);

                txtLifes = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.small),
                    ForeColor = MicroSnakeColors.MenuItemForeColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = lifes.ToString(),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtLifes.SetMargin(0, 0, 0, 10);
                infoStackPanel.Children.Add(txtLifes);

                // Add Remained Mouses Text
                txtRemainedMousesTitle = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.NinaB),
                    ForeColor = MicroSnakeColors.MenuItemSelectedBackgroundColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = Resources.GetString(Resources.StringResources.GameScreenRemainedMousesTitle),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtRemainedMousesTitle.SetMargin(0, 0, 0, 10);
                infoStackPanel.Children.Add(txtRemainedMousesTitle);

                txtRemainedMouees = new Text()
                {
                    Font = Resources.GetFont(Resources.FontResources.small),
                    ForeColor = MicroSnakeColors.MenuItemForeColor,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextAlignment = TextAlignment.Center,
                    TextContent = remainedMouses.ToString(),
                    VerticalAlignment = VerticalAlignment.Center,
                };
                txtRemainedMouees.SetMargin(0, 0, 0, 10);
                infoStackPanel.Children.Add(txtRemainedMouees);

            centerStackPanel.Children.Add(infoStackPanel);

            mainStackPanel.Children.Add(centerStackPanel);

            mainStackPanel.AddHandler(Buttons.ButtonDownEvent, new ButtonEventHandler(GameScreen_ButtonDown), false);

            this.Children.Add(mainStackPanel);
        }

        private void SetRound(short round)
        {
            this.round = round;
            txtRound.TextContent = round.ToString();
            txtRound.Invalidate();
        }

        private void SetLifes(short lifes)
        {
            this.lifes = lifes;
            txtLifes.TextContent = lifes.ToString();
            txtLifes.Invalidate();
        }

        private void SetRemainedMouses(short mouses)
        {
            this.remainedMouses = mouses;
            txtRemainedMouees.TextContent = mouses.ToString();
            txtRemainedMouees.Invalidate();
        }
        
        /*********************************************************************/
        /*                   Event Handling and Timer                        */
        /*********************************************************************/

        void GameScreen_ButtonDown(object sender, ButtonEventArgs e)
        {
            if (e.Button == Button.VK_SELECT)
            {
                if (gameStatus == GameStatus.NotStarted)
                {
                    StartGame();
                    gameTimer.Change(0, timerCounter);
                }
                else if (gameStatus == GameStatus.Running)
                {
                    gameStatus = GameStatus.Pause;
                    gameTimer.Change(Timeout.Infinite, Timeout.Infinite);
                }
                else if ( gameStatus == GameStatus.Pause )
                {
                    gameStatus = GameStatus.Running;
                    gameTimer.Change(0, timerCounter);
                }
            }

            if (gameStatus == GameStatus.Running)
            {
                if (e.Button == Button.VK_UP)
                {
                    snake.ChangeDirection(Direction.Up);
                }
                else if (e.Button == Button.VK_DOWN)
                {
                    snake.ChangeDirection(Direction.Down);
                }
                else if (e.Button == Button.VK_LEFT)
                {
                    snake.ChangeDirection(Direction.Left);
                }
                else if (e.Button == Button.VK_RIGHT)
                {
                    snake.ChangeDirection(Direction.Right);
                }
            }
        }

        public void GameUpdate()
        {
            snake.Update();
            gameBoard.Invalidate();
        }

        public void gameTimer_elapsed(object state)
        {
            this.Dispatcher.BeginInvoke(new GameTimerDelegate(GameUpdate));
        }

        /// <summary>
        /// Set the focus to the internal StackPanel
        /// </summary>
        public override void Focus()
        {
            Buttons.Focus(mainStackPanel);
        }
    }
}
